/*
Kakine
ActionScript Framework
Copyright © 2011, PUNY, LLC.

This file is part of KAKINE.

KAKINE is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

KAKINE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with KAKINE.  If not, see <http://www.gnu.org/licenses/>.
*/ 
package com.puny.utils
{
	import com.puny.mvc.views.View;
	
	import flash.display.BitmapData;
	import flash.display.BitmapDataChannel;
	import flash.filters.DisplacementMapFilter;
	import flash.filters.DisplacementMapFilterMode;
	import flash.geom.Point;
	
	/**
	 * Red is a channel for x-axis sift. Blue is for y-axis.
	 *  
	 * @author Mitsuru
	 * 
	 */
	public class DisplacementMapGenerator extends Object implements IDisplacementMapGenerator {
		private var _width:Number;
		private var _height:Number;
		private var _hw:Number;
		private var _hh:Number;
		private var _filter:DisplacementMapFilter;
		private var _bmpData:BitmapData
		private var _screen:View;
		private var _min:Point;
		private var _max:Point;

		public function DisplacementMapGenerator(width:Number,height:Number) {
			_width = width;
			_height = height;
			_hw = _width / 2;
			_hh = _height / 2;

			_bmpData = new BitmapData(_width,_height,false,0x000000);

			scanStage(range);
			if (_max.x > -_min.x) {
				_min.x = -_max.x;
			} else {
				_max.x = -_min.x;
			}			
			if (_max.y > -_min.y) {
				_min.y = -_max.y;
			} else {
				_max.y = -_min.y;
			}			
			scanStage(drawBitmapFilter);
			
			_filter = generateFilter();
		}
		
		protected function set width(value:Number):void {
			_width = value;
		}
		
		protected function get width():Number {
			return _width;
		}
		
		protected function set height(value:Number):void {
			_height = value;
		}
		
		protected function get height():Number {
			return _height;
		}
		
		/**
		 * 
		 * @param xdd sifted x position by displacement map filter
		 * @param ydd sifted y position by displacement map filter
		 * @return x and y position of source image.
		 * 
		 */
		protected function calcurate(xdd:Number,ydd:Number):Point {
			return new Point();
		}
		
		private function scanStage(proc:Function):void {
			for(var ydd:Number = -_hh;ydd <= _hh;ydd++) {
				for(var xdd:Number = -_hw;xdd <= _hw;xdd++) {
					var pt:Point = calcurate(xdd,ydd);
					proc(xdd, ydd, pt.x-xdd, pt.y-ydd);
				}
			}
			
		}
		
		private function range(px:Number,py:Number,dx:Number,dy:Number):void {
			if ( _min != null) {
				_min.x = (_min.x > dx) ? dx : _min.x;
				_min.y = (_min.y > dy) ? dy : _min.y;
			} else {
				_min = new Point(dx,dy);
			}
			if ( _max != null) {
				_max.x = (_max.x < dx) ? dx : _max.x;
				_max.y = (_max.y < dy) ? dy : _max.y;
			} else {
				_max = new Point(dx,dy);
			}
		}
		
		private function drawBitmapFilter(px:Number,py:Number,dx:Number,dy:Number):void {
			var r:uint;
			var b:uint;
			r = (dx - _min.x) / ( _max.x - _min.x) * 0xFF;
			b = (dy - _min.y) / ( _max.y - _min.y) * 0xFF;
			_bmpData.setPixel(px+_hw,py+_hh,r * 0x010000 + b);
		}
		
		private function generateFilter():DisplacementMapFilter {
			return new DisplacementMapFilter(_bmpData,
											 new Point(0,0),
											 BitmapDataChannel.RED,
											 BitmapDataChannel.BLUE,
											 _max.x-_min.x,
											 _max.y-_min.y,
											 DisplacementMapFilterMode.COLOR);
		}
		
		public function get bitmapData():BitmapData {
			return _bmpData;
		}
		
		public function get filter():DisplacementMapFilter {
			return _filter;
		}
		
	}
}